//------------------------Parameter----------------------
// sdram timing
localparam
    T_CLK = 8.000,  // clk cycle (ns)
    T_RP  = 18.0,   // precharge time (ns)
    T_RFC = 60.0,   // auto refresh time (ns)
    T_RAS = 42.0,   // active to precharge time (ns)
    T_MRD = 2,      // mode register set time (cycle)
    T_RCD = 18.0,   // active to read / write time (ns)
    T_WR  = 12.0;   // write recovery time

// sdram command
localparam
    // refer to "How To Use SDRAM, Table 2-1"
    // (MSB) cs_n -> ras_n -> cas_n -> we_n (LSB)
    SD_CMD_MRS  = 4'b0000, // mode register set
    SD_CMD_REF  = 4'b0001, // auto refresh
    SD_CMD_PRE  = 4'b0010, // precharge selected bank / all banks
    SD_CMD_ACT  = 4'b0011, // active bank and row
    SD_CMD_WRIT = 4'b0100, // write with / without auto precharge
    SD_CMD_READ = 4'b0101, // read with / without auto precharge
    SD_CMD_BST  = 4'b0110, // burst stop
    SD_CMD_NOP  = 4'b0111; // no operation

// delay
localparam
    // Quartus does not support real type :(
    DELAY_PU  = ceil(1000 * 1e5  , 1000 * T_CLK), // power up 100us
    DELAY_RP  = ceil(1000 * T_RP , 1000 * T_CLK), // T_RP
    DELAY_RFC = ceil(1000 * T_RFC, 1000 * T_CLK), // T_RFC
    DELAY_RAS = ceil(1000 * T_RAS, 1000 * T_CLK), // T_RAS
    DELAY_MRD = T_MRD,
    DELAY_RCD = ceil(1000 * T_RCD, 1000 * T_CLK), // T_RCD
    DELAY_WR  = ceil(1000 * T_WR , 1000 * T_CLK); // T_WR

// sdram mode register
localparam
    // refer to "How To Use SDRAM, Figure 4-7"
    SD_MR_CL = 3'd3, // cas latency  : 3
    SD_MR_WT = 1'b0, // wrap type    : sequential
    SD_MR_BL = 3'd2; // burst length : 4

// loop
localparam [3:0]
    LOOP_IREF = 4'd2, // init refresh times
    LOOP_AREF = 4'd8; // auto refresh row each time

// auto refresh
localparam
    REFRESH_CYCLE = ceil(64000000 / 2048 * LOOP_AREF * 1000, T_CLK * 1000);

//------------------------Task and function--------------
function integer ceil(input integer x, input integer y);
begin
        ceil = x / y;
        if (ceil * y < x) ceil = ceil + 1;
end
endfunction

// vim:set ts=4 sw=4 et fdm=marker fenc=utf-8 ft=verilog:
